/**
 * 
 */
package info.niwota.fwrite;

import info.niwota.fwrite.util.Base64;

import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;

import org.json.JSONObject;

import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Canvas;
import android.graphics.Paint;


/**
 * @author qiangli
 *
 */
public class ImageElement extends Element {
	
	private static final long serialVersionUID = 1L;

	private static final int DEFAULT_WIDTH = 100;

	private static final int DEFAULT_HEIGHT = 100;

	private String path;
	
	private JSONObject obj = null;
	
	private transient Bitmap bitmap = null;

	private transient int scale = 0;

	public ImageElement(String path) {
		this.path = path;
		this.width = DEFAULT_WIDTH;
		this.height = DEFAULT_HEIGHT;
	}
	
	public ImageElement(JSONObject obj) throws Exception {
		super(obj);
		
		this.path = obj.getString(KEY_PATH);
		//
		byte[] b = Base64.decode(obj.getString(KEY_BITMAP));
		this.bitmap = BitmapFactory.decodeByteArray(b, 0, b.length);
	}
	
	public JSONObject toJSON() throws Exception {
		JSONObject obj = super.toJSON(ELEMENT_IMAGE);
		
		obj.put(KEY_PATH, path);

		//send inline
		obj.put(KEY_BITMAP, compressBitmap());
		return obj;
	}
	
	private String compressBitmap() throws UnsupportedEncodingException {
		Bitmap bm = getBitmap();
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		bm.compress(CompressFormat.JPEG, 70, out);
		final String enc = Base64.encodeBytes(out.toByteArray());
		return enc;
	}
	
	private Bitmap getBitmap() {
		if (bitmap == null) {
			if (obj != null) {
				//invalid image from json
			} else {
				bitmap = loadImage();
			}
		}
		return bitmap;
	}
	
	@Override
	public void recompute(Paint paint) {
		Options opt = new Options();
		
		computeScale(opt);
		
		this.width = opt.outWidth * scale;
		this.height = opt.outHeight * scale;
	}
	
	private Bitmap loadImage() {
		Options opt = new Options();
		
		computeScale(opt);
		//
		opt.inJustDecodeBounds = false;
		opt.inSampleSize = scale;
		Bitmap bm = BitmapFactory.decodeFile(path, opt);
		
		return bm;
	}

	private void computeScale(Options opt) {
		if (path == null) {
			return;
		}
		if (scale > 0) {
			return;
		}
		opt.inJustDecodeBounds = true;
		BitmapFactory.decodeFile(path, opt);
		int w = opt.outWidth;
		int h = opt.outHeight;
		//
		float scalew = w / DEFAULT_WIDTH;
		float scaleh = h / DEFAULT_HEIGHT;
		
		this.scale = (int) Math.max(scalew, scaleh);
	}

	@Override
	public void draw(Canvas canvas, Paint paint, float x, float y,
			float height, float lh) {
		Bitmap bm = getBitmap();
		if (bm != null) {
			canvas.drawBitmap(bm, x, y, paint);
		}
	}
}
